#include "Game.h"

#include "SGD Wrappers/CSGD_Direct3D.h"
#include "SGD Wrappers/CSGD_DirectInput.h"
#include "SGD Wrappers/CSGD_TextureManager.h"
#include "SGD Wrappers/CSGD_XAudio2.h"

#include "GamePlayState.h"
#include "MainMenuState.h"

void Game::Update(void)
{
	// Refresh the XAudio2
	m_pXA->Update();

	// Calculate the elapsed time
	DWORD now = GetTickCount();
	float elapsed = (now - gameTime) / 1000.0f;
	gameTime = now;

	if(elapsed > 0.125f)
		elapsed = 0.125f;

	// Let Current State Handle Update
	curState->Update(elapsed);
}

void Game::Render(void)
{
	// Clear the background
	m_pD3D->Clear( 0, 0, 0 );

	// Start D3D rendering
	m_pD3D->DeviceBegin();
	m_pD3D->SpriteBegin();

	// Let the current state render
	curState->Render();

	m_pD3D->SpriteEnd();
	m_pD3D->DeviceEnd();

	m_pD3D->Present();
}

bool Game::Input(void)
{
	// Refresh the Direct Input buffers
	m_pDI->ReadDevices();

	return curState->Input();
}

void Game::ChangeState(IGameState* state)
{
	if( curState != nullptr )
		curState->Exit();

	curState = state;

	if( curState != nullptr )
		curState->Enter();
}

void Game::Init(HWND hwnd, HINSTANCE hinstance, int width, int height)
{
	// Access all the SGD Wrappers
	m_pD3D	= CSGD_Direct3D::GetInstance();
	m_pDI	= CSGD_DirectInput::GetInstance();
	m_pTM	= CSGD_TextureManager::GetInstance();
	m_pXA	= CSGD_XAudio2::GetInstance();

	// Initialize the wrappers
	m_pD3D->InitDirect3D( hwnd, width, height, fullScreen, false);
	m_pDI->InitDirectInput( hwnd, hinstance, DI_KEYBOARD | DI_MOUSE  | DI_JOYSTICKS);
	m_pTM->InitTextureManager( m_pD3D->GetDirect3DDevice(), m_pD3D->GetSprite() );
	m_pXA->InitXAudio2( );

	screenWidth = width;
	screenHeight = height;

	ChangeState( MainMenuState::GetInstance() );
}

bool Game::Main(void)
{
	// Sanity-check
	if(curState == nullptr)
		return false;

	if(Input() == false)
		return false;

	Update();
	Render();

	return true;
}

void Game::Shutdown(void)
{
	ChangeState(NULL);

	if( m_pXA != nullptr )
	{
		m_pXA->ShutdownXAudio2();
		m_pXA = nullptr;
	}

	if( m_pTM != nullptr )
	{
		m_pTM->ShutdownTextureManager();
		m_pTM = nullptr;
	}

	if( m_pDI != nullptr )
	{
		m_pDI->ShutdownDirectInput();
		m_pDI = nullptr;
	}

	if( m_pD3D != nullptr )
	{
		m_pD3D->ShutdownDirect3D();
		m_pD3D = nullptr;
	}

	// full screen turned off
	fullScreen = true;
}

Game::Game() 
{ 
	// full screen turned off
	fullScreen = true;
}
Game::~Game() { }

Game* Game::GetInstance(void)
{
	static Game instance;
	return &instance;
}

void Game::FullScreenOn()
{
	CSGD_Direct3D::GetInstance()->ChangeDisplayParam(screenWidth,screenHeight,fullScreen);
	CSGD_DirectInput::GetInstance()->ClearInput();
	CSGD_DirectInput::GetInstance()->ReadDevices();
}